<?php
declare(strict_types=1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;

/**
 * 文件路径迁移命令
 * 用于更新oa_file表中的filepath字段，从旧的模块区分格式转换为新的统一格式
 */
class MigrateFilePath extends Command
{
    protected function configure()
    {
        $this->setName('migrate:filepath')
            ->setDescription('迁移文件路径，从旧的模块区分格式转换为新的统一格式');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln('开始迁移文件路径...');
        
        try {
            // 查询所有需要更新的记录
            $files = Db::name('file')->select();
            
            $updatedCount = 0;
            $errorCount = 0;
            
            foreach ($files as $file) {
                $oldPath = $file['filepath'];
                $newPath = $this->convertFilePath($oldPath, $file['module']);
                
                // 如果路径有变化，则更新记录
                if ($newPath !== $oldPath) {
                    try {
                        Db::name('file')
                            ->where('id', $file['id'])
                            ->update(['filepath' => $newPath]);
                        
                        $updatedCount++;
                        $output->writeln("更新文件ID {$file['id']}: $oldPath -> $newPath");
                    } catch (\Exception $e) {
                        $errorCount++;
                        $output->writeln("<error>更新文件ID {$file['id']} 失败: " . $e->getMessage() . "</error>");
                    }
                }
            }
            
            $output->writeln("<info>迁移完成！成功更新 $updatedCount 条记录，失败 $errorCount 条记录。</info>");
            return 0;
        } catch (\Exception $e) {
            $output->writeln("<error>迁移失败: " . $e->getMessage() . "</error>");
            return 1;
        }
    }
    
    /**
     * 转换文件路径
     * @param string $oldPath 旧路径
     * @param string $module 模块名
     * @return string 新路径
     */
    private function convertFilePath($oldPath, $module)
    {
        // 如果已经是新格式（不包含模块名），则直接返回
        if (preg_match('/^uploads\/\d{6}\//', $oldPath)) {
            return $oldPath;
        }
        
        // 处理旧格式路径：uploads/{module}/{date}/{filename}
        if (preg_match('/^uploads\/' . preg_quote($module) . '\/(\d{6})\/(.+)$/', $oldPath, $matches)) {
            $date = $matches[1];
            $filename = $matches[2];
            return "uploads/$date/$filename";
        }
        
        // 处理其他可能的格式
        // 如果路径以storage开头，去掉storage前缀
        if (strpos($oldPath, 'storage/') === 0) {
            $oldPath = substr($oldPath, 8); // 去掉'storage/'前缀
            return $this->convertFilePath($oldPath, $module);
        }
        
        // 如果路径以/开头，去掉/
        if (strpos($oldPath, '/') === 0) {
            $oldPath = substr($oldPath, 1);
            return $this->convertFilePath($oldPath, $module);
        }
        
        // 其他情况，尝试提取日期和文件名
        if (preg_match('/(\d{6})\/(.+)$/', $oldPath, $matches)) {
            $date = $matches[1];
            $filename = $matches[2];
            return "uploads/$date/$filename";
        }
        
        // 如果无法匹配任何格式，则保持原样
        return $oldPath;
    }
}